<template>
    <a-layout>
        <a-layout-content
                :style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"
        >
            <p>
                <!-- 这里可以直接用一个name作为响应式变量，但考虑到后续可能通过多个参数来查询，为了扩展性，统一封装成一个param对象 -->
                <a-form layout="inline" :model="param">
                    <a-form-item>
                        <a-input v-model:value="param.loginName" placeholder="登录名" />
                    </a-form-item>
                    <a-form-item>
                        <!-- 下面的 pagination 是响应式变量，在html中试用响应式变量，无需.value -->
                        <a-button type="primary" @click="handleQuery({pageNum:1, pageSize: pagination.pageSize})">查询</a-button>
                    </a-form-item>
                    <a-form-item>
                        <a-button type="primary" @click="handleAdd">新增</a-button>
                    </a-form-item>
                </a-form>
            </p>
            <a-table
                    :columns="columns"
                    :data-source="users"
                    :row-key="record => record.id"
                    :pagination="pagination"
                    :loading="loading"
                    @change="handleTableChange"
            >
                <template #action="{ text, record }">
                    <a-space size="small">
                        <a-button type="primary" @click="handleResetPassword(record)">重置密码</a-button>
                        <a-button type="primary" @click="handleEdit(record)">编辑</a-button>
                        <a-popconfirm
                                title="删除后不可恢复，确认删除?"
                                ok-text="是"
                                cancel-text="否"
                                @confirm="handleDelete(record.id)"
                        >
                            <!-- 在 2.2.0 之后，危险成为一种按钮属性而不是按钮类型 -->
                            <a-button type="primary" danger>删除</a-button>
                        </a-popconfirm>
                    </a-space>
                </template>
            </a-table>
        </a-layout-content>
    </a-layout>
    <a-modal
            title="用户表单"
            v-model:visible="modalVisible"
            :confirm-loading="modalLoading"
            @ok="handleModalOk">
        <a-form :model="user" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
            <a-form-item label="登录名">
                <!-- 编辑时，user.id会有值；新增时，没有值。所以可通过该值控制编辑时，登录名不可修改。-->
                <!-- 【小技巧】不直接:disabled="user.id"，因为属性disabled需要一个Boolean类型，vue会有警告，可以用!!绕过类型校验 -->
                <a-input v-model:value="user.loginName" :disabled="!!user.id"/>
            </a-form-item>
            <a-form-item label="昵称">
                <a-input v-model:value="user.name" />
            </a-form-item>
            <a-form-item label="密码" v-show="!user.id">
                <a-input-password v-model:value="user.password"/>
            </a-form-item>
        </a-form>
    </a-modal>
    <a-modal
            title="重置密码"
            v-model:visible="resetModalVisible"
            :confirm-loading="resetModalLoading"
            @ok="handleResetModalOk">
        <a-form :model="user" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
            <a-form-item label="新密码">
                <a-input-password v-model:value="user.password"/>
            </a-form-item>
        </a-form>
    </a-modal>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import axios from 'axios';
import { message } from 'ant-design-vue';
import {Tool} from "@/util/tool";

// hexMd5方法和KEY常量，已经在index.html中引入了对应js文件了，可以直接用，但vue的TypeScript还不知道，编译会报错。用declare，告诉该文件，下面两个变量是存在的。
declare let hexMd5: any;    // 函数（字符串转为32位的16进制字符串）
declare let KEY: any;       // 盐值

export default defineComponent({
  name: 'AdminUser',
  setup() {
    const param = ref() ; // 定义一个响应式变量，并初始化为空。用于存放搜索框中的内容）
    param.value = {} ;           //若不初始化，页面加载时param.name会出错，因为页面加载时就会读取该属性值
    const users = ref(); // ref方式，实现数据绑定
    const pagination = ref({
        current: 1,
        pageSize: 3,
        total: 0
    });
    const loading = ref(false);

    // 表格参数：title指定列名；dataIndex指定值渲染，slots为自定义渲染（其中title自定义列名，customRender自定义值；html中要有对应template），key保持唯一即可
    const columns = [
      {
        title: '登录名',
        dataIndex: 'loginName',
        key: 'loginName'
      },
      {
        title: '昵称',
        dataIndex: 'name',
        key: 'name',
      },
      {
        title: '密码',
        dataIndex: 'password',
        key: 'password'
      },
      {
        title: 'Action',
        key: 'action',
        slots: { customRender: 'action' },
      },
    ];

    /** 数据查询 */
    const handleQuery = (params: any) => {
        loading.value = true;   // 加载中
        axios.get("/user/list", {
            params: {
                pageNum: params.pageNum,
                pageSize: params.pageSize,
                loginName: param.value.loginName
            }
        }).then((response) => {
            loading.value = false;  // 加载完成
            const data = response.data ;
            if(data.success){
                users.value = data.content.list ; //ref方式，赋值

                // 重置分页按钮（否则分页栏不会聚焦在当前页）
                pagination.value.current = params.pageNum;
                // 设置总数（否则后端分页后，前端无法得知总页数，会将返回结果list作为总记录数，导致总是显示1页）
                pagination.value.total =  data.content.total;
            }else {
                message.error(data.message);
            }
        });
    };

    /** 表格点击页码时触发 */
    const handleTableChange = (pagination: any) => {
        console.log("看看自带的分页参数都有啥：" , pagination);
        handleQuery({
            // 这里的pagination是一个普通的函数参数（可以随意命名，如pag），与onMounted中我们用的ref响应式变量不一样，所以不用x.value.y
            pageNum: pagination.current,
            pageSize: pagination.pageSize
        });
    };

    // ---- 用户表单 ----
    const user = ref();
    const modalVisible = ref(false);
    const modalLoading = ref(false);
    const handleModalOk = () => {
        modalLoading.value = true;

        user.value.password = hexMd5(user.value.password + KEY) ;   // 前端针对密码进行MD5加密，避免传输报文被截获泄露

        axios.post("/user/save", user.value).then((response) => {
            modalLoading.value = false;     // 后台返回结果后，Modal框的加载动画关闭
            const data = response.data ;
            // 后台返回成功后，关闭Modal弹框，并刷新列表
            if(data.success){
                modalVisible.value = false; // 后台返回成功结果后，Modal框关闭
                // 重新刷新本页
                handleQuery({
                    // 这里的pagination用的是ref响应式变量
                    pageNum: pagination.value.current,
                    pageSize: pagination.value.pageSize
                });
            }else {
                message.error(data.message);
            }
        });
    }

    /** 编辑 */
    const handleEdit = (record: any) => {
        modalVisible.value = true ;
        // record是响应式变量users中的记录，直接复制给user这个编辑框中的响应式变量，会导致编辑一半不保存直接关闭编辑框的情况下，users中的记录也会跟着变化
        user.value = Tool.copy(record) ; // 用对象拷贝，解决响应式变量复制的影响
    }

    /** 新增 */
    const handleAdd = () => {
        modalVisible.value = true ;
        user.value = {} ;
    }

    /** 删除 */
    const handleDelete = (id: number) => {
        axios.delete("/user/delete/" + id).then((response) => {
            const data = response.data ; // data = CommonResp
            // 删除成功后，刷新列表
            if(data.success){
                handleQuery({
                    pageNum: pagination.value.current,
                    pageSize: pagination.value.pageSize
                });
            }else {
                message.error(data.message);
            }
        });
    }

    // ---- 重置密码表单 ----
    const resetModalVisible = ref(false);
    const resetModalLoading = ref(false);
    const handleResetModalOk = () => {
        resetModalLoading.value = true;

        user.value.password = hexMd5(user.value.password + KEY) ;   // 前端针对密码进行MD5加密，避免传输报文被截获泄露

        axios.post("/user/reset-password", user.value).then((response) => {
            resetModalLoading.value = false;     // 后台返回结果后，Modal框的加载动画关闭
            const data = response.data ;
            // 后台返回成功后，关闭Modal弹框，并刷新列表
            if(data.success){
                resetModalVisible.value = false; // 后台返回成功结果后，Modal框关闭
                // 重新刷新本页
                handleQuery({
                    // 这里的pagination用的是ref响应式变量
                    pageNum: pagination.value.current,
                    pageSize: pagination.value.pageSize
                });
            }else {
                message.error(data.message);
            }
        });
    }

    /** 重置密码 */
    const handleResetPassword = (record: any) => {
        resetModalVisible.value = true ;
        user.value = Tool.copy(record) ;
        user.value.password = null ; // 将重置密码弹出框的密码输入域置空
    }

    onMounted(() => {
        handleQuery({
            pageNum: 1,
            pageSize: pagination.value.pageSize
        }) ;
    });

    return {
      param,
      users,
      columns,
      pagination,
      loading,
      handleTableChange,
      handleQuery, // HTML中需要调用，所以要return出去

      handleEdit,
      handleAdd,
      handleDelete,

      user,
      modalVisible,
      modalLoading,
      handleModalOk,

      resetModalVisible,
      resetModalLoading,
      handleResetModalOk,
      handleResetPassword
    };
  },

});
</script>